# -*- coding: utf-8 -*-
"""
Module Description: chaos_orm sdk接口

吐槽:
remote_api/log/log_util.py::deco_log::_deco调用pack_error_log的那一行的第一个参数是args[-1],
导致调用remote_api/models/remote_call/http_api.py中的dal方法时,比如将traceid作为最后一个参数传递, 而且只能以*args的方式传,
于是就有了下面调用http_api时, 多个参数顺序摆放的代码...

Date: 2018/8/2
Author:Bai Jin Ping
"""
import copy

from remote_api.models.remote_call import http_api
from pyshare.framework import runtime_logger as log


def insert_model(db_name, mdl_cls, values, trace_id=None):
    return http_api.insert_model(
        db_name,
        mdl_cls.__name__,
        values,
        trace_id
    )


def delete_model(db_name, mdl_cls, conditions, operator="AND", trace_id=None):
    """
    @return: {"code": int, "info": string}
    @ not_sql提供占位符,让服务端判断是否要执行sql语句
    """
    chaos_conditions = _parse_in_condition(conditions)

    return http_api.delete_model(
        db_name,
        mdl_cls.__name__,
        mdl_cls.get_primary_keys(),
        chaos_conditions,
        operator,
        trace_id
    )


def update_model(db_name, model_name, pks, values, conditions, operator="AND", trace_id=None):
    """
    @return: {"code": int, "info": string}
    @ not_sql提供占位符,让服务端判断是否要执行sql语句
    """
    chaos_conditions = _parse_in_condition(conditions)

    return http_api.update_model(
        db_name,
        model_name,
        pks,
        values,
        chaos_conditions,
        operator,
        trace_id
    )


def select_model(db_name, model_name, pks, conditions, columns=None,
                 operator="AND", order=None, limit=None, offset=0, trace_id=None):
    """
    @return: {"code": int, "info": string}
    @ not_sql提供占位符,让服务端判断是否要执行sql语句
    """
    chaos_conditions = _parse_in_condition(conditions)

    return http_api.select_model(
        db_name,
        model_name,
        pks,
        chaos_conditions,
        columns,
        operator,
        order,
        limit,
        offset,
        trace_id
    )


def select_count(db_name, mdl_cls, conditions, trace_id=None):
    """
    返回记录数
    """
    from pyshare.framework.dal.orm.controller_api import AggregateCount

    chaos_conditions = _parse_in_condition(conditions)

    return http_api.select_model(
        db_name,
        mdl_cls.__name__,
        mdl_cls.get_primary_keys(),
        chaos_conditions,
        [AggregateCount.get_column_name()],
        "AND",
        None,
        None,
        0,
        trace_id
    )


def select_min(db_name, mdl_cls, field_name, conditions, trace_id=None):
    """
    返回最小值
    """
    from pyshare.framework.dal.orm.controller_api import AggregateMin

    chaos_conditions = _parse_in_condition(conditions)

    return http_api.select_model(
        db_name,
        mdl_cls.__name__,
        mdl_cls.get_primary_keys(),
        chaos_conditions,
        [AggregateMin.get_column_name(field_name)],
        "AND",
        None,
        None,
        0,
        trace_id
    )


def select_max(db_name, mdl_cls, field_name, conditions, trace_id=None):
    """
    返回最大值
    """
    from pyshare.framework.dal.orm.controller_api import AggregateMax

    chaos_conditions = _parse_in_condition(conditions)

    return http_api.select_model(
        db_name,
        mdl_cls.__name__,
        mdl_cls.get_primary_keys(),
        chaos_conditions,
        [AggregateMax.get_column_name(field_name)],
        "AND",
        None,
        None,
        0,
        trace_id
    )


def transaction_model(trans_obj, work, trace_id=None):
    """
    事务
    url: /[db]
    body: [
        {"orm": "对象名", "pk": "主键名", "action": "insert", "body": {"字段名": 字段值, ...}},
        {"orm": "对象名", "pk": "主键名", "action": "delete", "body": {"字段名__运算符": 字段值, ...}},
        {"orm": "对象名", "pk": "主键名", "action": "update", "body": {"values": {"字段名": 字段值, ...},
        "conditions": {"字段名__运算符": 字段值, ..., "operator": "AND[OR]"}},
        ...
        ]
    @ not_sql提供占位符,让服务端判断是否要执行sql语句
    @return: {"code": int, "info": string}
    """
    for trans in work:
        if trans.get('action') == 'delete':
            # delete操作时, body就是condition
            trans['body'] = _parse_in_condition(trans['body'])
        else:
            trans['body']['conditions'] = _parse_in_condition(trans['body'].get('conditions'))

    return http_api.transaction_model(
        work,
        trace_id
    )


def query_sql(db_name, sql, trace_id):
    """
    @sql 让客户端判断执行sql语句
    """
    return http_api.query_sql(
        db_name,
        sql,
        trace_id
    )


def _parse_in_condition(conditions):
    """
    chaos的in参数需要转换为字符串
    :param conditions:
    """
    if not conditions:
        return {}

    in_cdts_dict = {}
    for k, v in conditions.iteritems():
        if k.endswith('__in') and v:
            in_cdts_dict[k] = str([str(e) for e in v])

    if in_cdts_dict:
        # 返回新的字典作为发给chaos_orm服务的参数, 不影响dal.orm后续逻辑
        new_conditions = copy.deepcopy(conditions)
        new_conditions.update(in_cdts_dict)
        return new_conditions
    else:
        return conditions
